package core

import (
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"gitee.com/StarCitizen_CN/logger"
	"gitee.com/StarCitizen_CN/stargox/pkg/gitee"
)

var (
	FUpdateMode   = flag.Bool("updateMode", false, "")
	fUpdateTarget = flag.String("updateTarget", "", "")
	fUpdateDelay  = flag.Duration("updateDelay", 1*time.Second, "")
)

func CheckReleaseWithGitee(giteeRepoAddress string, mirrors []string) (isUpdateRequired bool, release *gitee.Release, err error) {
	var giteeCheckErr error
	release, giteeCheckErr = gitee.GetLastReleaseWithGitee(giteeRepoAddress, "")
	if giteeCheckErr != nil {
		for _, mirror := range mirrors {
			release, giteeCheckErr = gitee.GetLastReleaseWithGitee(giteeRepoAddress, mirror)
			if giteeCheckErr != nil {
				continue
			}
			goto onSuccess
		}

		return false, nil, giteeCheckErr
	}

onSuccess:
	if release.TagName == GitVersion {
		return false, release, nil
	}

	return true, release, nil
}

// 仅适用于单个可执行文件的更新
// 并且下载完后应当及时退出(在updateDelay期限内)
//
// SelfUpdateWithGitee(wdPath, "name*", assets, "3s")
// 需要接收者接受参数：-updateMode  -updateTarget  -updateDelay 3s
func SelfUpdateWithGitee(asset *gitee.ReleaseAssets, wdPath, tempDirName, updateDelay string, cb gitee.DownloadCB) (bool, error) {

	if err := CheckAndCrateOsTemp(); err != nil {
		return false, err
	}

	if asset != nil {
		tempDir, mkDirTempErr := os.MkdirTemp(TempDir, tempDirName)
		if mkDirTempErr != nil {
			return false, mkDirTempErr
		}

		filePath := filepath.Join(tempDir, asset.Name)
		if e := gitee.Download(asset.GetDownloadUrl(), filePath, cb); e != nil {
			return false, e
		}

		cmdArgs := []string{"-updateMode", "-updateTarget", os.Args[0], "-updateDelay", updateDelay}
		logger.Var("下载完成 \n %s\n%v", filePath, cmdArgs)

		cmd := exec.Command(filePath, cmdArgs...)
		if runErr := cmd.Start(); runErr != nil {
			logger.ShowGuiMsg("在试图运行更新程序的过程中发现异常", runErr.Error())
			return false, runErr
		}
		cmd.Process.Release()

	} else {
		return false, fmt.Errorf("没有附件")
	}

	return true, nil
}

// 在这里继续完成升级
func ContinueSelfUpdate() error {

	time.Sleep(*fUpdateDelay)

	selfPath := os.Args[0]

	f, readErr := os.Open(selfPath)
	if readErr != nil {
		return readErr
	}

	var try int
	for {
		if try > 30 {
			return os.ErrDeadlineExceeded
		}
		time.Sleep(time.Second * 3)
		if err := os.Remove(*fUpdateTarget); err != nil {
			if os.IsNotExist(err) {
				break
			}
		}
		try += 1
	}

	tf, openTFErr := os.OpenFile(*fUpdateTarget, os.O_WRONLY|os.O_SYNC|os.O_TRUNC|os.O_CREATE, os.ModeAppend)
	if openTFErr != nil {
		return openTFErr
	}

	_, copyErr := io.Copy(tf, f)
	if copyErr != nil {
		return copyErr
	}

	return nil
}
